﻿using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using OSGeo.MapServer;
using System.IO;

public partial class _Default : System.Web.UI.Page 
{
    private mapObj mapa;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack) //First access to the map
        {
            //send image stream from MapServer to ibMap
            ibMap.ImageUrl = "MapStream.aspx?ACTION=INITMAP";
            //initialize controls
            mapa = new mapObj(System.Configuration.ConfigurationSettings.AppSettings["mapFilePath"].ToString());
            //iterate the map layer to populate ddlLayer and cblLayer
            for (int i = 0; i < mapa.numlayers; i++)
            {
                layerObj layer = mapa.getLayer(i);
                ddlLayers.Items.Add(layer.name);
                cblLayers.Items.Add(layer.name);
                //If this condition is true, the layer is visible
                if (layer.status == (int)mapscript.MS_ON)
                {
                    cblLayers.Items[i].Selected = true;
                }
            }
        }
        else //Next accesses to the map, let's get it from session
        {
            mapa = (mapObj)Session["MAP"];
        }

    }
    protected void ibMap_Click(object sender, ImageClickEventArgs e)
    {
        lblInfo.Text = "";
        String Action = "";
        String activeLayer = ddlLayers.SelectedItem.Text;
        //we have to check what GIS tool is needed
        switch (rblGisTools.SelectedItem.Text.ToUpper())
        {
            case "PANEO":
                Action = "PANEO";
                break;
            case "ZOOM IN":
                Action = "ZOOMIN";
                break;
            case "ZOOM OUT":
                Action = "ZOOMOUT";
                break;
            case "IDENTIFY":
                Action = "IDENTIFY";
                break;
            case "BONDI":
                Action = "CLICK";
                break;
        }
        //For Identify let's call DoIdentify
        if (Action.Equals("IDENTIFY"))
        {
            DoIdentify(e.X, e.Y, activeLayer);
        }
        //For Add Point let's call Click
        if (Action.Equals("CLICK"))
        {
            String[,] fieldValues = new String[2, 2];
            fieldValues[0, 0] = "POI_USER";
            fieldValues[0, 1] = "Nicolás";
            fieldValues[1, 0] = "POI_TIME";
            fieldValues[1, 1] = DateTime.Now.ToShortDateString() + ", " + System.DateTime.Now.ToLongTimeString();
            Click(e.X, e.Y, activeLayer, fieldValues);
        }
        //Stream map image to ibMap according to the needed GIS Action
        ibMap.ImageUrl = "MapStream.aspx?ACTION=" + Action + "&X=" + e.X + "&Y=" + e.Y + "&ACTIVELAYER=" + activeLayer;

    }
    protected void butFullExtent_Click(object sender, EventArgs e)
    {
        ibMap.ImageUrl = "MapStream.aspx?ACTION=FULLEXTENT";
    }

    private void Click(Double x, Double y, String activeLayer, String[,] fieldValues)
    {
        //check: this action is valid only for point shapefiles
        pointObj point = pixel2point(new pointObj(x, y, 0, 0)); //conver the image point in map point
        //notify action
        //lblInfo.Text = "This action can be performed only on point shapefiles.";
        if (mapa.getLayerByName("montevideo").queryByPoint(mapa, point, (int)mapscript.MS_SINGLE, 200) == (int)MS_RETURN_VALUE.MS_SUCCESS)
        {
            resultCacheObj results = mapa.getLayerByName("montevideo").getResults();
            mapa.getLayerByName("montevideo").open();
            resultCacheMemberObj rslt = mapa.getLayerByName("montevideo").getResult(0);
            shapeObj shape = new shapeObj(0);
            if (mapa.getLayerByName("montevideo").getShape(shape, rslt.tileindex, rslt.shapeindex) == (int)MS_RETURN_VALUE.MS_SUCCESS)
            {
                string resultadoConsulta = shape.values[2];
                litIdentifyResult.Text = "<center>Nombre de la calle consultada:<b> " + resultadoConsulta + "</b></center>";
            }
            else
            {
                litIdentifyResult.Text = "No pudo realizar la consulta 2, vuelva a intentar !!";
            }
        }
        else
        {
            litIdentifyResult.Text = "No pudo realizar la consulta 1, vuelva a intentar !!";
        }


        // Buscar líneas de bondi que pasan cerca
        if (mapa.getLayerByName("lineas").queryByPoint(mapa, point, (int)mapscript.MS_MULTIPLE, 200) == (int)MS_RETURN_VALUE.MS_SUCCESS)
        {
            resultCacheObj results = mapa.getLayerByName("lineas").getResults();
            mapa.getLayerByName("lineas").open();
            for (int i = 0; i < results.numresults && i < 5; i++)
            {
                resultCacheMemberObj rslt = mapa.getLayerByName("lineas").getResult(i);
                shapeObj shape = new shapeObj(0);
                if (mapa.getLayerByName("lineas").getShape(shape, rslt.tileindex, rslt.shapeindex) == (int)MS_RETURN_VALUE.MS_SUCCESS)
                {
                    string resultadoConsulta = shape.values[3];
                    litIdentifyResult.Text += "<center>Linea de omnibus que pasa por ahi:<b> " + resultadoConsulta + "</b><br></center>";
                }
                else
                {
                    litIdentifyResult.Text = "No pudo realizar la consulta 4, vuelva a intentar !!";
                } 
            }
        }
        else
        {
            litIdentifyResult.Text = "No pudo realizar la consulta 3, vuelva a intentar !!";
        }


    }

    /// <summary>
    /// Let's do identify
    /// </summary>
    /// <param name="x">x image coordinate for the point to identify</param>
    /// <param name="y">y image coordinate for the point to identify</param>
    /// <param name="activeLayer">layer to identify</param>
    private void DoIdentify(Double x, Double y, String activeLayer)
    {
        litIdentifyResult.Text = "";
        //identify
        layerObj layer = mapa.getLayerByName(activeLayer);
        if (layer != null)
        {
            layer.template = "dummy"; //for historical reasons
            pointObj point = pixel2point(new pointObj(x, y, 0, 0)); //conver the image point in map point
            double tolerance = mapa.width / 100; //we use this tolerance
            if (layer.queryByPoint(mapa, point, mapscript.MS_SINGLE, tolerance) == (int)MS_RETURN_VALUE.MS_SUCCESS)
            {
                //there is a feature to identify
                resultCacheObj result = layer.getResults();
                if (result.numresults > 0)
                {
                    int shapeInd = result.getResult(0).shapeindex;
                    //int tileInd = result.getResult(0).tileindex;
                    layer.open();
                    shapeObj shape = layer.getFeature(shapeInd, -1);
                    //iterate fields and getting values
                    for (int i = 0; i < layer.numitems; i++)
                    {
                        litIdentifyResult.Text += "<BR><B>" + layer.getItem(i) + "</B>=" + shape.getValue(i);
                    }
                    layer.close();
                }
            }
            else
            {
                //there is nothing to identify
                System.Diagnostics.Debug.WriteLine("Nothing to identify.");
            }
        }
    }

    /// <summary>
    /// Conver pixel point coordinates to map point coordinates
    /// </summary>
    /// <param name="pointPixel">pixel point (from map Image)</param>
    /// <returns></returns>
    private pointObj pixel2point(pointObj pointPixel)
    {
        rectObj extent = mapa.extent;
        double mapWidth = extent.maxx - extent.minx;
        double mapHeight = extent.maxy - extent.miny;
        double xperc;
        double yperc;
        xperc = pointPixel.x / mapa.width;
        yperc = (mapa.height - pointPixel.y) / mapa.height;
        double x = extent.minx + xperc * mapWidth;
        double y = extent.miny + yperc * mapHeight;
        pointObj pointMap = new pointObj(x, y, 0, 0);
        return pointMap;
    }
    protected void butRefresh_Click(object sender, EventArgs e)
    {
        //iterate layers and check visibility
        for (int i = 0; i < cblLayers.Items.Count; i++)
        {
            layerObj layer = mapa.getLayerByName(cblLayers.Items[i].Text);
            if (cblLayers.Items[i].Selected)
            {
                layer.status = (int)mapscript.MS_ON;
            }
            else
            {
                layer.status = (int)mapscript.MS_OFF;
            }
        }
        //send image stream from MapServer to ibMap
        ibMap.ImageUrl = "MapStream.aspx?ACTION=REFRESHMAP";

    }
    protected void butClear_Click(object sender, EventArgs e)
    {
        String shapeFullPath = mapa.shapepath + "\\" + ddlLayers.SelectedItem.Text + ".shp";
        layerObj layer = mapa.getLayerByName(ddlLayers.SelectedItem.Text);
        if (layer.type != MS_LAYER_TYPE.MS_LAYER_POINT || layer.connectiontype != MS_CONNECTION_TYPE.MS_SHAPEFILE)
        {
            //notify action
            lblInfo.Text = "This action can be performed only on point shapefiles.";
        }
        else
        {
            //Clear the point shapefile by copying its copy
            //Create a DirectoryInfo object representing the specified directory.
            DirectoryInfo dir = new DirectoryInfo(mapa.shapepath);
            //Get the FileInfo objects for every file that belongs to shapefile in the directory.
            FileInfo[] files = dir.GetFiles(ddlLayers.SelectedItem.Text + "Copy.*");
            for (int i = 0; i < files.Length; i++)
            {
                //be sure to put a copy of the point shapefile under shapepath, the copy should be called as NameCopy (ie: for POI of this tutorial, we put a shapefile copy called POICopy)
                File.Copy(files[i].FullName, mapa.shapepath + "\\" + ddlLayers.SelectedItem.Text + files[i].Extension, true);
            }
            //notify action
            lblInfo.Text = "Shapefile cleared.";
        }
        ibMap.ImageUrl = "MapStream.aspx?ACTION=LAYERDELETE";

    }
}
